package triIndex;

import transaction.*;
import triBasic.*;
import triInstance.*;
import triDataStruct.*;
import triEvent.*;
import utils.Constants;

public class IndexManager implements CreateNodeEventHandler, InsertItemEventHandler, RemoveItemEventHanlder, TriModule{

	private Str2IntIndex tagIndex;
	
	private Str2IntIndex itemIndex;
	
	private NodeIndex nodeIndex;
	
	public IndexManager() {
		HashFunction hashT = new StringHash();
		HashFunction hashI = new StringHash();
		
		nodeIndex = new NodeIndex(Constants.NODE_IDX_FILENAME, Constants.NODE_IDX_PAGEBUFFER_SIZE,
				Constants.NODE_IDX_PAGESIZE, Constants.NODE_IDX_META_FILENAME,  
				Constants.NODE_IDX_PAGEBUFFER_SIZE, Constants.NODE_IDX_META_PAGESIZE);
		
		tagIndex = new Str2IntIndex(hashT, Constants.TAG_IDX_MAPBUFFER_SIZE,
				Constants.TAG_IDX_FILENAME, 
				Constants.TAG_IDX_PAGEBUFFER_SIZE, 
				Constants.TAG_IDX_PAGESIZE,
				Constants.TAG_IDX_INODE_FILENAME,
				Constants.TAG_IDX_INODE_PAGEBUFFER_SIZE,
				Constants.TAG_IDX_INODE_PAGESIZE,
				Constants.TAG_BPTree_FILENAME,
				Constants.TAG_BPTree_PAGEBUFFER_SIZE, 
				Constants.TAG_BPTree_PAGESIZE,
				Constants.TAG_BPTree_ORDER);
		
		itemIndex = new Str2IntIndex(hashI, Constants.ITEM_IDX_MAPBUFFER_SIZE,
				Constants.ITEM_IDX_FILENAME, 
				Constants.ITEM_IDX_PAGEBUFFER_SIZE, 
				Constants.ITEM_IDX_PAGESIZE,
				Constants.ITEM_IDX_INODE_FILENAME,
				Constants.ITEM_IDX_INODE_PAGEBUFFER_SIZE,
				Constants.ITEM_IDX_INODE_PAGESIZE,
				Constants.ITEM_BPTree_FILENAME,
				Constants.ITEM_BPTree_PAGEBUFFER_SIZE, 
				Constants.ITEM_BPTree_PAGESIZE,
				Constants.ITEM_BPTree_ORDER);
	}
	
	@Override
	public void init(Transaction tx) {
		this.itemIndex.init(tx);
		this.tagIndex.init(tx);
		this.nodeIndex.init(tx);
	}

	@Override
	public void dispose(Transaction tx) {
		this.itemIndex.dispose(tx);
		this.tagIndex.dispose(tx);
		this.nodeIndex.dispose(tx);
	}
	
	public void compact(TxManager txMgr) {
		this.itemIndex.compact(Constants.TAG_IDX_FILENAME_TEMP, Constants.TAG_IDX_INODE_FILENAME_TEMP, txMgr);
	}
	
	@Override
	public void handleRemoveItem(TriItem item, NodeSnapshot snapshot, Transaction tx) {
		itemIndex.remove(item.convert2String(), snapshot.getNodeId(), tx);
	}

	@Override
	public void handleInsertItem(TriItem item, NodeSnapshot snapshot, Transaction tx) {
		itemIndex.insert(item.convert2String(), snapshot.getNodeId(), tx);
	}

	@Override
	public void handleCreateNode(NodeSnapshot snapshot, INode node, Transaction tx) {
		nodeIndex.createNewNode(snapshot, node, tx);
		tagIndex.insert(snapshot.getTagName(), snapshot.getNodeId(), tx);
	}
	
	public ISet<Integer> getItem2NodeId(TriItem item, Transaction tx) {
		CondQueryIntSet set = itemIndex.find(item.convert2String(), tx);
		return set;
	}
	
	public ISet<Integer> getTag2NodeId(String tagname, Transaction tx) {
		CondQueryIntSet set = tagIndex.find(tagname, tx);
		System.out.println("Tag2NodeId Set == null ? " + (set == null));
		return set;
	}
	
	public NodeSnapshot getNodeSnapshot(NodeInfo info, Transaction tx) {
		NodeSnapshot snapshot = nodeIndex.getNodeSnapshot(info.getNodeId(), tx);
		if (snapshot.getNodeId() != info.getNodeId() || 
				!snapshot.getTagName().equals(info.getTagName()))
			return null;
		
		return snapshot;
	}

	public NodeSnapshot getNodeSnapshot(int nodeId, Transaction tx) {
		return nodeIndex.getNodeSnapshot(nodeId, tx);
	}

	public TriPath getTriPath(NodeInfo info, Transaction tx) {
		NodeSnapshot snapshot = this.getNodeSnapshot(info, tx);
		if (snapshot == null)
			return null;
		TriPath path = nodeIndex.getTriPath(info.getNodeId(), tx);
		
		return path;
	}
	
}
